/*
    Project:        Home Power Control
    File:           HPCUnit.h
    Author:         christian@karunamusic.at
    Date:           12.2014
    Description:    A collection of sensors grouped together.
 */

#ifndef HPCUNIT_H
#define HPCUNIT_H

#include <boost/signals2.hpp>
#include <string>
#include <vector>

#include "HPCSensorValue.h"
#include "HPCSensor.h"


/** \brief A collection of sensors grouped together.
 * A unit has its own eventhandler for any of its sensors changed values.
 */
class HPCUnit
{
public:
    /** \brief Typedefinition of the callbackmethod for changed values.
     *
     * \param sender pointer to the sender of the notification.
     * \param sensor pointer to the sensor which have changed.
     * \param val HPCSensorValue - changed value of the sensor.
     * \return nothing.
     *
     */
    typedef boost::signals2::signal<void(HPCUnit *,HPCSensor *,const HPCSensorValue &)> TSignalChange;
    /** \brief Typedefinition of the callbackmethod for alarmed values.
     *
     * \param sender pointer to the sender of the notification.
     * \param sensor pointer to the sensor which have changed.
     * \param val HPCSensorValue - changed value of the sensor.
     * \param max if true alarm is raised because of val >= max, otherwise val <= min.
     * \param ndx index of the alarmvalue.
     * \return nothing.
     *
     */
    typedef boost::signals2::signal<void(HPCUnit *,HPCSensor *,const HPCSensorValue &,bool,unsigned int)> TSignalAlarm;
    /** \brief A connection type.
     */
    typedef boost::signals2::connection TConnection;

    /** \brief Constructor.
     *
     * \param id The database id.
     * \param name The name of the unit.
     *
     */
    HPCUnit( unsigned long id, std::string name );

    /** \brief Destructor.
     */
    virtual ~HPCUnit();

    /** \brief get the unit id.
     *
     * \return unsigned long with id.
     *
     */
    inline unsigned long ID() const
        { return m_ID; }

    /** \brief get the unit name.
     *
     * \return string with name.
     *
     */
    inline std::string Name() const
        { return m_Name; }

    /** \brief Get unit with its sensors as printable string.
     *
     * \return string
     *
     */
    std::string asString() const;

    /** \brief Set eventhandler for changed values.
     *
     * \param subscriber method called if the value of the sensor has changed.
     * \return connection handler.
     *
     */
    TConnection OnChange( const TSignalChange::slot_type &subscriber );

    /** \brief Set eventhandler for alarmed values.
     *
     * \param subscriber method called if the value of the sensor is out of limits.
     * \return connection handler.
     *
     */
    TConnection OnAlarm( const TSignalAlarm::slot_type &subscriber );

    /** \brief Add a sensor to the unit.
     * Add a sensor to the unit and connect to its eventhandler.
     * \param sens The sensor.
     * \return The unit.
     *
     */
    virtual HPCUnit& operator += ( HPCSensor* sens );

protected:
    /** \brief Internal eventhandler to catch changed sensors.
     *
     * \param sender The sensor.
     * \param val The changed value.
     *
     */
    virtual void SensorChanged( HPCSensor* sender, const HPCSensorValue& val );

    /** \brief Internal eventhandler to catch alarmed sensors.
     *
     * \param sender The sensor.
     * \param val The changed value.
     * \param _max If true alarm is raised because of val >= max, otherwise val <= min.
     *
     */
    virtual void SensorAlarmed( HPCSensor* sender, const HPCSensorValue& val, bool _max, unsigned int index );

private:
    unsigned long m_ID; /**< The database id. */
    std::string m_Name; /**< The name of the unit. */
    std::vector<HPCSensor*> m_Sensors; /**< Vector of sensors attached to the unit. */
    TSignalChange m_OnChange; /**< the callback-method for changed values. */
    TSignalAlarm  m_OnAlarm;  /**< the callback-method for alarmed values. */
};

#endif // HPCUNIT_H
